library(Seurat)
library(Signac)
library(EnsDb.Mmusculus.v79)
library(ggplot2)
counts <- Read10X_h5(paste0(params$out_prefix,"scATAC_P50/data/atac_v1_adult_brain_fresh_5k_filtered_peak_bc_matrix.h5"))
metadata <- read.csv(
  file = paste0(params$out_prefix,"scATAC_P50/data/atac_v1_adult_brain_fresh_5k_singlecell.csv"),
  header = TRUE,
  row.names = 1
)

fragment.path <- paste0(params$out_prefix,"scATAC_P50/data/atac_v1_adult_brain_fresh_5k_fragments.tsv.gz")

brain <- CreateSeuratObject(
  counts = counts,
  assay = 'peaks',
  project = 'ATAC',
  min.cells = 1,
  meta.data = metadata
)
Some cells in meta.data not present in provided counts matrix.
brain <- SetFragments(
  object = brain,
  file = fragment.path
)
brain <- RunTFIDF(brain)
Performing TF-IDF normalization
brain <- FindTopFeatures(brain, min.cutoff = 'q0')
brain <- RunSVD(
  object = brain,
  assay = 'peaks',
  reduction.key = 'LSI_',
  reduction.name = 'lsi'
)
Running SVD
Scaling cell embeddings
brain <- RunUMAP(object = brain, reduction = 'lsi', dims = 2:30)
11:57:47 UMAP embedding parameters a = 0.9922 b = 1.112
11:57:47 Read 3880 rows and found 29 numeric columns
11:57:47 Using Annoy for neighbor search, n_neighbors = 30
11:57:47 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
11:57:47 Writing NN index file to temp file /var/folders/zc/29jxbf153g37b_cjp6_gkxnxxh967n/T//RtmpZ9ef1K/file34ac66f4ddd2
11:57:47 Searching Annoy index using 1 thread, search_k = 3000
11:57:48 Annoy recall = 100%
11:57:49 Commencing smooth kNN distance calibration using 1 thread
11:57:51 Initializing from normalized Laplacian + noise
11:57:51 Commencing optimization for 500 epochs, with 144690 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
11:57:56 Optimization finished
brain <- FindNeighbors(object = brain, reduction = 'lsi', dims = 2:30)
Computing nearest neighbor graph
Computing SNN
brain <- FindClusters(object = brain, verbose = FALSE, algorithm = 3)
DimPlot(object = brain, label = TRUE) + NoLegend()

gene.coords <- ensembldb::genes(EnsDb.Mmusculus.v79, filter = ~ gene_biotype == "protein_coding")
lncRNA.coords <- ensembldb::genes(EnsDb.Mmusculus.v79, filter = ~ gene_biotype == "lincRNA")
gene.coords <- c(gene.coords,lncRNA.coords)

seqlevelsStyle(gene.coords) <- 'UCSC'
genebody.coords <- keepStandardChromosomes(gene.coords, pruning.mode = 'coarse')

# Flatten the overlapping genes and extend by 2kb upstream of promoters
genebody.coords.flat <- GenomicRanges::reduce(x = genebody.coords)
genebodyandpromoter.coords.flat <- Signac::Extend(genebody.coords.flat,upstream = 2000)

# Retrieve gene names from the original annotation (lost because of flatenning)
genebodyandpromoter.coords.flat$name<- gene.coords[nearest(genebodyandpromoter.coords.flat,genebody.coords)]$gene_name
gene.activities <- FeatureMatrix(
  fragments = fragment.path,
  features = genebodyandpromoter.coords.flat,
  cells = colnames(brain),
  chunk = 20
)
Extracting reads overlapping genomic regions

  |                                                  | 0 % ~calculating  
  |+++                                               | 5 % ~17m 06s      
markers       <- read.csv2(file=paste0(params$out_prefix,'Sten_RNA/clustering/sten_RNA_markers.csv'),row.names = 1)
assay='GA'


brain.markers.ls <- lapply(unique(markers$cluster),function(x){
  marker.genes <- markers[markers$cluster==x & markers$p_val_adj < 0.05 & markers$avg_logFC > 0,"gene"]
  marker.genes <- head(marker.genes,200)
  marker.genes.agg.exp <- Matrix::colSums(brain[[assay]]@data[rownames(brain[[assay]]) %in% marker.genes,])
  marker.genes.agg.exp <- marker.genes.agg.exp / Matrix::colSums(brain[[assay]]@counts)
  return(marker.genes.agg.exp)
})

names(brain.markers.ls)  <- gsub("-",".",unique(markers$cluster))
markers.agg.df           <- do.call(cbind,brain.markers.ls)
colnames(markers.agg.df) <- paste0("marker_",gsub(" ",".",colnames(markers.agg.df)))


brain <- AddMetaData(brain,metadata = markers.agg.df,col.name = colnames(markers.agg.df))



lapply(as.character(colnames(markers.agg.df)),function(x){
  FeaturePlot(brain,x,max.cutoff = quantile(markers.agg.df[,x],0.9,na.rm=TRUE),min.cutoff = quantile(markers.agg.df[,x],0.05,na.rm=TRUE)) + scale_color_viridis_c() + NoLegend()
  #FeaturePlot(brain,x,max.cutoff = 0.08,min.cutoff = 0.02) + scale_color_viridis_c(limits=c(0.02,0.08)) 
  })
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]

[[9]]

[[10]]

[[11]]

[[12]]

[[13]]

[[14]]

[[15]]

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

[[21]]

[[22]]

[[23]]

[[24]]

[[25]]

[[26]]

[[27]]

[[28]]

[[29]]

[[30]]

[[31]]

[[32]]

[[33]]

[[34]]

[[35]]

[[36]]

[[37]]

[[38]]

[[39]]

brain <- RenameIdents(brain,'4' = "mOL",'8' = 'mOL','12' = 'OPC','5' = "Astrocytes",'10'='Astrocytes')
DimPlot(brain,label=TRUE) + NoLegend()

rr paste0(params\(out_prefix,params\)antibody,/bigwig/cluster_,cluster,.bw)

[1] \~/mount/CT/git_test/results/scATAC_P50/bigwig/cluster_olig.bw\
f
Error: object 'f' not found

rr saveRDS(object = brain,file = paste0(params\(out_prefix,params\)antibody,/clustering/clustering_scATAC.Rds))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCnBhcmFtczoKICBvdXRfcHJlZml4OiAifi9tb3VudC9DVC9naXRfdGVzdC9yZXN1bHRzLyIKICBhbnRpYm9keTogJ3NjQVRBQ19QNTAnCi0tLQoKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNpZ25hYykKbGlicmFyeShFbnNEYi5NbXVzY3VsdXMudjc5KQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKYGBge3J9CmNvdW50cyA8LSBSZWFkMTBYX2g1KHBhc3RlMChwYXJhbXMkb3V0X3ByZWZpeCwic2NBVEFDX1A1MC9kYXRhL2F0YWNfdjFfYWR1bHRfYnJhaW5fZnJlc2hfNWtfZmlsdGVyZWRfcGVha19iY19tYXRyaXguaDUiKSkKbWV0YWRhdGEgPC0gcmVhZC5jc3YoCiAgZmlsZSA9IHBhc3RlMChwYXJhbXMkb3V0X3ByZWZpeCwic2NBVEFDX1A1MC9kYXRhL2F0YWNfdjFfYWR1bHRfYnJhaW5fZnJlc2hfNWtfc2luZ2xlY2VsbC5jc3YiKSwKICBoZWFkZXIgPSBUUlVFLAogIHJvdy5uYW1lcyA9IDEKKQoKZnJhZ21lbnQucGF0aCA8LSBwYXN0ZTAocGFyYW1zJG91dF9wcmVmaXgsInNjQVRBQ19QNTAvZGF0YS9hdGFjX3YxX2FkdWx0X2JyYWluX2ZyZXNoXzVrX2ZyYWdtZW50cy50c3YuZ3oiKQoKYnJhaW4gPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KAogIGNvdW50cyA9IGNvdW50cywKICBhc3NheSA9ICdwZWFrcycsCiAgcHJvamVjdCA9ICdBVEFDJywKICBtaW4uY2VsbHMgPSAxLAogIG1ldGEuZGF0YSA9IG1ldGFkYXRhCikKCmJyYWluIDwtIFNldEZyYWdtZW50cygKICBvYmplY3QgPSBicmFpbiwKICBmaWxlID0gZnJhZ21lbnQucGF0aAopCmBgYAoKYGBge3J9CmJyYWluIDwtIFJ1blRGSURGKGJyYWluKQpicmFpbiA8LSBGaW5kVG9wRmVhdHVyZXMoYnJhaW4sIG1pbi5jdXRvZmYgPSAncTAnKQpicmFpbiA8LSBSdW5TVkQoCiAgb2JqZWN0ID0gYnJhaW4sCiAgYXNzYXkgPSAncGVha3MnLAogIHJlZHVjdGlvbi5rZXkgPSAnTFNJXycsCiAgcmVkdWN0aW9uLm5hbWUgPSAnbHNpJwopCgpicmFpbiA8LSBSdW5VTUFQKG9iamVjdCA9IGJyYWluLCByZWR1Y3Rpb24gPSAnbHNpJywgZGltcyA9IDI6MzApCmJyYWluIDwtIEZpbmROZWlnaGJvcnMob2JqZWN0ID0gYnJhaW4sIHJlZHVjdGlvbiA9ICdsc2knLCBkaW1zID0gMjozMCkKYnJhaW4gPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IGJyYWluLCB2ZXJib3NlID0gRkFMU0UsIGFsZ29yaXRobSA9IDMpCkRpbVBsb3Qob2JqZWN0ID0gYnJhaW4sIGxhYmVsID0gVFJVRSkgKyBOb0xlZ2VuZCgpCmBgYAoKCmBgYHtyIGxvYWRfZ2VuZV9hbm5vdGF0aW9uc30KZ2VuZS5jb29yZHMgPC0gZW5zZW1ibGRiOjpnZW5lcyhFbnNEYi5NbXVzY3VsdXMudjc5LCBmaWx0ZXIgPSB+IGdlbmVfYmlvdHlwZSA9PSAicHJvdGVpbl9jb2RpbmciKQpsbmNSTkEuY29vcmRzIDwtIGVuc2VtYmxkYjo6Z2VuZXMoRW5zRGIuTW11c2N1bHVzLnY3OSwgZmlsdGVyID0gfiBnZW5lX2Jpb3R5cGUgPT0gImxpbmNSTkEiKQpnZW5lLmNvb3JkcyA8LSBjKGdlbmUuY29vcmRzLGxuY1JOQS5jb29yZHMpCgpzZXFsZXZlbHNTdHlsZShnZW5lLmNvb3JkcykgPC0gJ1VDU0MnCmdlbmVib2R5LmNvb3JkcyA8LSBrZWVwU3RhbmRhcmRDaHJvbW9zb21lcyhnZW5lLmNvb3JkcywgcHJ1bmluZy5tb2RlID0gJ2NvYXJzZScpCgojIEZsYXR0ZW4gdGhlIG92ZXJsYXBwaW5nIGdlbmVzIGFuZCBleHRlbmQgYnkgMmtiIHVwc3RyZWFtIG9mIHByb21vdGVycwpnZW5lYm9keS5jb29yZHMuZmxhdCA8LSBHZW5vbWljUmFuZ2VzOjpyZWR1Y2UoeCA9IGdlbmVib2R5LmNvb3JkcykKZ2VuZWJvZHlhbmRwcm9tb3Rlci5jb29yZHMuZmxhdCA8LSBTaWduYWM6OkV4dGVuZChnZW5lYm9keS5jb29yZHMuZmxhdCx1cHN0cmVhbSA9IDIwMDApCgojIFJldHJpZXZlIGdlbmUgbmFtZXMgZnJvbSB0aGUgb3JpZ2luYWwgYW5ub3RhdGlvbiAobG9zdCBiZWNhdXNlIG9mIGZsYXRlbm5pbmcpCmdlbmVib2R5YW5kcHJvbW90ZXIuY29vcmRzLmZsYXQkbmFtZTwtIGdlbmUuY29vcmRzW25lYXJlc3QoZ2VuZWJvZHlhbmRwcm9tb3Rlci5jb29yZHMuZmxhdCxnZW5lYm9keS5jb29yZHMpXSRnZW5lX25hbWUKYGBgCgpgYGB7cn0KZ2VuZS5hY3Rpdml0aWVzIDwtIEZlYXR1cmVNYXRyaXgoCiAgZnJhZ21lbnRzID0gZnJhZ21lbnQucGF0aCwKICBmZWF0dXJlcyA9IGdlbmVib2R5YW5kcHJvbW90ZXIuY29vcmRzLmZsYXQsCiAgY2VsbHMgPSBjb2xuYW1lcyhicmFpbiksCiAgY2h1bmsgPSAyMAopCmdlbmUua2V5ICAgICAgICAgICAgICAgICAgPC0gZ2VuZWJvZHlhbmRwcm9tb3Rlci5jb29yZHMuZmxhdCRuYW1lCm5hbWVzKGdlbmUua2V5KSAgICAgICAgICAgPC0gR1Jhbmdlc1RvU3RyaW5nKGdyYW5nZSA9IGdlbmVib2R5YW5kcHJvbW90ZXIuY29vcmRzLmZsYXQpCnJvd25hbWVzKGdlbmUuYWN0aXZpdGllcykgPC0gZ2VuZS5rZXlbcm93bmFtZXMoZ2VuZS5hY3Rpdml0aWVzKV0KZ2VuZS5hY3Rpdml0aWVzICAgICAgICAgICA8LSBnZW5lLmFjdGl2aXRpZXNbcm93bmFtZXMoZ2VuZS5hY3Rpdml0aWVzKSAhPSAiIixdCgpicmFpbltbJ0dBJ11dICAgICAgICAgICAgIDwtIENyZWF0ZUFzc2F5T2JqZWN0KGNvdW50cyA9IGdlbmUuYWN0aXZpdGllcykKYGBgCgoKYGBge3J9Cm1hcmtlcnMgICAgICAgPC0gcmVhZC5jc3YyKGZpbGU9cGFzdGUwKHBhcmFtcyRvdXRfcHJlZml4LCdTdGVuX1JOQS9jbHVzdGVyaW5nL3N0ZW5fUk5BX21hcmtlcnMuY3N2Jykscm93Lm5hbWVzID0gMSkKYXNzYXk9J0dBJwoKCmJyYWluLm1hcmtlcnMubHMgPC0gbGFwcGx5KHVuaXF1ZShtYXJrZXJzJGNsdXN0ZXIpLGZ1bmN0aW9uKHgpewogIG1hcmtlci5nZW5lcyA8LSBtYXJrZXJzW21hcmtlcnMkY2x1c3Rlcj09eCAmIG1hcmtlcnMkcF92YWxfYWRqIDwgMC4wNSAmIG1hcmtlcnMkYXZnX2xvZ0ZDID4gMCwiZ2VuZSJdCiAgbWFya2VyLmdlbmVzIDwtIGhlYWQobWFya2VyLmdlbmVzLDIwMCkKICBtYXJrZXIuZ2VuZXMuYWdnLmV4cCA8LSBNYXRyaXg6OmNvbFN1bXMoYnJhaW5bW2Fzc2F5XV1AZGF0YVtyb3duYW1lcyhicmFpbltbYXNzYXldXSkgJWluJSBtYXJrZXIuZ2VuZXMsXSkKICBtYXJrZXIuZ2VuZXMuYWdnLmV4cCA8LSBtYXJrZXIuZ2VuZXMuYWdnLmV4cCAvIE1hdHJpeDo6Y29sU3VtcyhicmFpbltbYXNzYXldXUBjb3VudHMpCiAgcmV0dXJuKG1hcmtlci5nZW5lcy5hZ2cuZXhwKQp9KQoKbmFtZXMoYnJhaW4ubWFya2Vycy5scykgIDwtIGdzdWIoIi0iLCIuIix1bmlxdWUobWFya2VycyRjbHVzdGVyKSkKbWFya2Vycy5hZ2cuZGYgICAgICAgICAgIDwtIGRvLmNhbGwoY2JpbmQsYnJhaW4ubWFya2Vycy5scykKY29sbmFtZXMobWFya2Vycy5hZ2cuZGYpIDwtIHBhc3RlMCgibWFya2VyXyIsZ3N1YigiICIsIi4iLGNvbG5hbWVzKG1hcmtlcnMuYWdnLmRmKSkpCgoKYnJhaW4gPC0gQWRkTWV0YURhdGEoYnJhaW4sbWV0YWRhdGEgPSBtYXJrZXJzLmFnZy5kZixjb2wubmFtZSA9IGNvbG5hbWVzKG1hcmtlcnMuYWdnLmRmKSkKCgoKbGFwcGx5KGFzLmNoYXJhY3Rlcihjb2xuYW1lcyhtYXJrZXJzLmFnZy5kZikpLGZ1bmN0aW9uKHgpewogIEZlYXR1cmVQbG90KGJyYWluLHgsbWF4LmN1dG9mZiA9IHF1YW50aWxlKG1hcmtlcnMuYWdnLmRmWyx4XSwwLjksbmEucm09VFJVRSksbWluLmN1dG9mZiA9IHF1YW50aWxlKG1hcmtlcnMuYWdnLmRmWyx4XSwwLjA1LG5hLnJtPVRSVUUpKSArIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYygpICsgTm9MZWdlbmQoKQogICNGZWF0dXJlUGxvdChicmFpbix4LG1heC5jdXRvZmYgPSAwLjA4LG1pbi5jdXRvZmYgPSAwLjAyKSArIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYyhsaW1pdHM9YygwLjAyLDAuMDgpKSAKICB9KQoKCmBgYAoKCgpgYGB7cn0KYnJhaW4gPC0gUmVuYW1lSWRlbnRzKGJyYWluLCc0JyA9ICJtT0wiLCc4JyA9ICdtT0wnLCcxMicgPSAnT1BDJywnNScgPSAiQXN0cm9jeXRlcyIsJzEwJz0nQXN0cm9jeXRlcycpCkRpbVBsb3QoYnJhaW4sbGFiZWw9VFJVRSkgKyBOb0xlZ2VuZCgpCmBgYAoKYGBge3IsZmlnLndpZHRoPTEwLGZpZy5oZWlnaHQ9MTB9CmJyYWluLlJOQSAgICAgICAgICAgICAgPC0gcmVhZFJEUyhwYXN0ZTAocGFyYW1zJG91dF9wcmVmaXgsJ1N0ZW5fUk5BL2NsdXN0ZXJpbmcvMDEuY2x1c3RlcmluZ18yMDAwMGNlbGxzLlJkcycpKQpicmFpbi5STkEgICAgICAgICAgICAgIDwtIFNldElkZW50KGJyYWluLlJOQSxjZWxscyA9IGNvbG5hbWVzKGJyYWluLlJOQSksdmFsdWUgPSBhcy5mYWN0b3IoZ3N1YigiICIsIl8iLGJyYWluLlJOQSRUYXhvbm9teVJhbms0KSkpCgojIFJlc2V0IHNjQVRBQyBjbHVzdGVyIG5hbWVzCmJyYWluQGFjdGl2ZS5pZGVudCA8LSBhcy5mYWN0b3IoYnJhaW4kc2V1cmF0X2NsdXN0ZXJzKQoKRGltUGxvdChicmFpbi5STkEsbGFiZWw9VFJVRSxyZXBlbCA9IFRSVUUpICsgTm9MZWdlbmQoKQpEaW1QbG90KGJyYWluLGxhYmVsPVRSVUUpICsgTm9MZWdlbmQoKQpgYGAKCmBgYHtyLGZpZy53aWR0aD0xNCxmaWcuaGVpZ2h0PTE0fQpEZWZhdWx0QXNzYXkoYnJhaW4pIDwtICJHQSIKIyBmZWF0dXJlcyA9IGludGVyc2VjdChyb3duYW1lcyhicmFpbikscm93bmFtZXMoYnJhaW4uUk5BKSkKYnJhaW4uUk5BIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKG9iamVjdCA9IGJyYWluLlJOQSxuZmVhdHVyZXMgPSA1MDAwKQoKdHJhbnNmZXIuYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKAogIHJlZmVyZW5jZSA9IGJyYWluLlJOQSwKICBxdWVyeSA9IGJyYWluLAogIHJlZHVjdGlvbiA9ICdjY2EnKSMgLGsuZmlsdGVyID0gTkEpCgpwcmVkaWN0ZWQubGFiZWxzIDwtIFRyYW5zZmVyRGF0YSgKICBhbmNob3JzZXQgPSB0cmFuc2Zlci5hbmNob3JzLAogIHJlZmRhdGEgPSBicmFpbi5STkFAYWN0aXZlLmlkZW50LAogIHdlaWdodC5yZWR1Y3Rpb24gPSBicmFpbltbJ2xzaSddXSwKICBkaW1zID0gMjozMAopCgpicmFpbiA8LSBBZGRNZXRhRGF0YShvYmplY3QgPSBicmFpbiwgbWV0YWRhdGEgPSBwcmVkaWN0ZWQubGFiZWxzKQpwbG90MSA8LSBEaW1QbG90KAogIG9iamVjdCA9IGJyYWluLlJOQSwKICBncm91cC5ieSA9ICdUYXhvbm9teVJhbms0JywKICBsYWJlbCA9IFRSVUUsCiAgcmVwZWwgPSBUUlVFKSArIE5vTGVnZW5kKCkgKyBnZ3RpdGxlKCdzY1JOQS1zZXEnKQoKcGxvdDIgPC0gRGltUGxvdCgKICBvYmplY3QgPSBicmFpbiwKICBncm91cC5ieSA9ICdwcmVkaWN0ZWQuaWQnLAogIGxhYmVsID0gVFJVRSwKICByZXBlbCA9IFRSVUUpICsgTm9MZWdlbmQoKSArIGdndGl0bGUoJ3NjQVRBQy1zZXEnKQoKcGxvdDEgKyBwbG90MgpgYGAKYGBge3J9CgpjaHJvbS5zaXplcyA8LSByZWFkLnRhYmxlKHVybCgnaHR0cDovL2hnZG93bmxvYWQuY3NlLnVjc2MuZWR1L2dvbGRlblBhdGgvbW0xMC9iaWdaaXBzL21tMTAuY2hyb20uc2l6ZXMnKSxzZXA9Ilx0IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmNocm9tLnNpemVzIDwtIGNocm9tLnNpemVzWzE6MjEsXQoKZXhwb3J0QlcgPC0gZnVuY3Rpb24ob2JqZWN0LGNsdXN0ZXIsZnJhZ21lbnRzKXsKICBpZihjbGFzcyhvYmplY3QpID09ICJTZXVyYXQiKXsKICAgIGNlbGxzIDwtIHJvd25hbWVzKG9iamVjdEBtZXRhLmRhdGFbb2JqZWN0QGFjdGl2ZS5pZGVudCA9PSBjbHVzdGVyLF0pCiAgfQogIGlmKGxlbmd0aChjZWxscyk9PTApe3JldHVybihwYXN0ZTAoIk5vIGNlbGxzIGZvdW5kIGZvciBjbHVzdGVyICIsY2x1c3RlcikpfQogIAogIG5ld19yZWFkIDwtIEdSYW5nZXMoc2VxbmFtZXMgPSBjaHJvbS5zaXplc1ssMV0sIAogICAgICAgICAgcmFuZ2VzID1JUmFuZ2VzKHN0YXJ0ID0gYXMubnVtZXJpYyhjaHJvbS5zaXplc1ssMl0pLAogICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTEpLAogICAgICAgICAgbmFtZSA9ICJpbl9zaWxpY29fZXh0cmFfcmVhZCIsCiAgICAgICAgICBzY29yZSA9IDAKICAgICAgICAgICkKICAKICBmcmFnbWVudHMueCA8LSBmcmFnbWVudHMkbmFtZSAlaW4lIGNlbGxzCiAgZnJhZ21lbnRzLnggPC0gZnJhZ21lbnRzW2ZyYWdtZW50cy54XQogIGZyYWdtZW50cy54IDwtIGMoZnJhZ21lbnRzLngsbmV3X3JlYWQpCiAgCiAgCiAgY292ZXJhZ2UueCA8LSBjb3ZlcmFnZShmcmFnbWVudHMueCkKICAKICAjIE9wdGlvbiBBIC0gbm9ybWFsaXplIGJ5IG51bWJlciBvZiByZWFkcyBwZXIgc2FtcGxlCiAgY292ZXJhZ2UueCA8LSBjb3ZlcmFnZS54LyhsZW5ndGgoZnJhZ21lbnRzLngpLzFlNikKICAKICAjIE9wdGlvbiBCIC0gbm9ybWFsaXplIGJ5IG1lYW4gc2lnbmFsICh+IGVucmljaG1lbnQgb2YgbWVhbiBzaWduYWwpCiAgIyBjb3ZlcmFnZS54IDwtIGNvdmVyYWdlLnggLyBtZWFuKHVubGlzdChjb3ZlcmFnZS54KSkKICAKICBydHJhY2tsYXllcjo6ZXhwb3J0LmJ3KG9iamVjdCA9IGNvdmVyYWdlLngscGFzdGUwKHBhcmFtcyRvdXRfcHJlZml4LHBhcmFtcyRhbnRpYm9keSwiL2NsdXN0ZXJpbmcvYmlnd2lnL2NsdXN0ZXJfIixjbHVzdGVyLCIuYnciKSkKfQoKZnJhZ21lbnRzIDwtIHJ0cmFja2xheWVyOjppbXBvcnQoZnJhZ21lbnQucGF0aCxmb3JtYXQgPSAnYmVkJykKCmJyYWluQGFjdGl2ZS5pZGVudCA8LSBhcy5mYWN0b3IoYnJhaW4kcHJlZGljdGVkLmlkKQpleHBvcnRCVyhicmFpbiwnT2xpZ29kZW5kcm9jeXRlcycsZnJhZ21lbnRzKQpleHBvcnRCVyhicmFpbiwnQXN0cm9jeXRlcycsZnJhZ21lbnRzKQpleHBvcnRCVyhicmFpbiwnT2xpZ29kZW5kcm9jeXRlX3ByZWN1cnNvcl9jZWxscycsZnJhZ21lbnRzKQpgYGAKCmBgYHtyfQpjbHVzdGVyLmFubm90YXRpb25zICAgICAgICAgICA8LSBhcy5kYXRhLmZyYW1lKGJyYWluQGFjdGl2ZS5pZGVudFticmFpbkBhY3RpdmUuaWRlbnQgJWluJSBjKCdPbGlnb2RlbmRyb2N5dGVzJywnQXN0cm9jeXRlcycsJ09saWdvZGVuZHJvY3l0ZV9wcmVjdXJzb3JfY2VsbHMnLCdWYXNjdWxhcl9hbmRfbGVwdG9tZW5pbmdlYWxfY2VsbHMnKV0pCgpjbHVzdGVyLmFubm90YXRpb25zJGJhcmNvZGUgICA8LSByb3duYW1lcyhjbHVzdGVyLmFubm90YXRpb25zKQpyb3duYW1lcyhjbHVzdGVyLmFubm90YXRpb25zKSA8LSBOVUxMCmNvbG5hbWVzKGNsdXN0ZXIuYW5ub3RhdGlvbnMpIDwtIGMoJyNjbHVzdGVyJywgJyNiYXJjb2RlJykKCndyaXRlLmNzdih4ID0gY2x1c3Rlci5hbm5vdGF0aW9ucywgZmlsZT1wYXN0ZTAocGFyYW1zJG91dF9wcmVmaXgscGFyYW1zJGFudGlib2R5LCcvY2x1c3RlcmluZy9iYW1fcGVyX2NsdXN0ZXIvY2x1c3Rlcl9iYXJjb2RlX3RhYmxlLmNzdicpLHJvdy5uYW1lcyA9IEZBTFNFLHF1b3RlID0gRkFMU0UsKQoKYGBgCgoKYGBge3J9CnNhdmVSRFMob2JqZWN0ID0gYnJhaW4sZmlsZSA9IHBhc3RlMChwYXJhbXMkb3V0X3ByZWZpeCxwYXJhbXMkYW50aWJvZHksIi9jbHVzdGVyaW5nL2NsdXN0ZXJpbmdfc2NBVEFDLlJkcyIpKQpgYGAKCgoKCgoKCgoKCgoKCgoKCgoKCg==